package com.qst.order.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qst.order.controller.AdminController;
import com.qst.order.domain.DTO.*;
import com.qst.order.domain.Product;
import com.qst.order.domain.ProductSpec;
import com.qst.order.domain.ProductSpecPrice;
import com.qst.order.domain.ReplenishRecord;
import com.qst.order.domain.VO.ProductBase;
import com.qst.order.domain.VO.ProductSpecVO;
import com.qst.order.domain.VO.SpecPriceMapItem;
import com.qst.order.exception.BusinessException;
import com.qst.order.mapper.ProductMapper;
import com.qst.order.mapper.ProductSpecMapper;
import com.qst.order.mapper.ProductSpecPriceMapper;
import com.qst.order.mapper.ReplenishRecordMapper;
import com.qst.order.service.ProductService;
import com.qst.order.utils.JsonUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {


    private final ProductMapper productMapper;

    private final ProductSpecMapper specMapper;

    private  final ProductSpecPriceMapper specPriceMapper;

    private final ReplenishRecordMapper replenishRecordMapper;

    // 添加ObjectMapper用于手动解析JSON
    private final ObjectMapper objectMapper;

    // 从配置文件读取默认预警阈值（也可从数据库配置表查询）
    @Value("${product.warning.default-threshold:10}")
    private Integer defaultThreshold;

    // 严重不足比例（库存 ≤ 阈值的30%）
    @Value("${product.warning.critical-ratio:30}")
    private Integer criticalRatio;

    // 库存偏低比例（库存 ≤ 阈值的60%）
    @Value("${product.warning.warning-ratio:60}")
    private Integer warningRatio;


    @Override
    @Cacheable(value = "product",
            key = "#root.methodName + '[' + #category + '][' + #keyword + '][' + #minPrice + '][' + #maxPrice + '][' + #sort + '][' + #pageNum + '][' + #pageSize + ']'")
    public Page<Product> getAllProducts(String category, String keyword, BigDecimal minPrice,
                                        BigDecimal maxPrice, String sort, int pageNum, int pageSize) {
        // 保持原有逻辑不变
        if (minPrice != null && maxPrice != null && minPrice.compareTo(maxPrice) > 0) {
            throw new IllegalArgumentException("最小价格不能大于最大价格");
        }
        Page<Product> page = new Page<>(pageNum, pageSize);
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();

        if (StringUtils.isNotBlank(category)) {
            queryWrapper.eq("category", category);
        }

        if (StringUtils.isNotBlank(keyword)) {
            queryWrapper.and(wrapper -> wrapper
                    .like("product_name", keyword)
                    .or()
                    .like("title", keyword));
        }

        if (minPrice != null) {
            queryWrapper.ge("price", minPrice);
        }
        if (maxPrice != null) {
            queryWrapper.le("price", maxPrice);
        }

        if (StringUtils.isNotBlank(sort)) {
            switch (sort) {
                case "price_asc":
                    queryWrapper.orderByAsc("price");
                    break;
                case "price_desc":
                    queryWrapper.orderByDesc("price");
                    break;
                case "id_desc":
                    queryWrapper.orderByDesc("product_id");
                    break;
                default:
                    queryWrapper.orderByAsc("product_id");
            }
        } else {
            queryWrapper.orderByAsc("product_id");
        }
        queryWrapper.eq("status", 1);// 只查询正常状态的商品

        return productMapper.selectPage(page, queryWrapper);
    }

    @Override
    public ProductSpecVO getSpecAndPriceByProductId(Integer productId) {
        // 1. 查询商品基础信息
        Product product = productMapper.selectById(productId);
        ProductBase productBase = new ProductBase();
        BeanUtils.copyProperties(product, productBase);
        productBase.setDefaultPrice(product.getPrice());
        log.warn("商品信息：{}", product);
        log.warn("商品信息：{}", productBase);
        // 2. 查询规格选项列表（使用通用解析工具）
        Map<String, List<String>> specOptions = new HashMap<>();
        try {
            QueryWrapper<ProductSpec> specQuery = new QueryWrapper<>();
            specQuery.eq("product_id", productId);
            ProductSpec productSpec = specMapper.selectOne(specQuery);

            if (productSpec != null && StringUtils.isNotBlank(productSpec.getSpec())) {
                // 兼容正常JSON和双重编码JSON
                specOptions = JsonUtils.parseSpecOptions(productSpec.getSpec());
            } else {
                log.warn("商品{}未找到规格信息或规格为空", productId);
            }
        } catch (Exception e) {
            log.error("解析规格JSON失败", e);
            specOptions = new HashMap<>();
        }

        // 3. 查询规格-价格映射（使用通用解析工具）
        List<ProductSpecPrice> specPriceList = specPriceMapper.selectList(
                new QueryWrapper<ProductSpecPrice>().eq("product_id", productId)
        );
        List<SpecPriceMapItem> specPriceMap = new ArrayList<>();

        for (ProductSpecPrice specPrice : specPriceList) {
            SpecPriceMapItem vo = new SpecPriceMapItem();
            if (specPrice.getSpecCombo() != null) {
                // 兼容正常JSON和双重编码JSON
                Map<String, String> specCombo = JsonUtils.parseSpecCombo(specPrice.getSpecCombo());
                vo.setSpecCombo(specCombo);
            } else {
                vo.setSpecCombo(new HashMap<>());
            }
            vo.setPrice(specPrice.getPrice());
            specPriceMap.add(vo);
        }

        // 4. 组装返回结果
        ProductSpecVO result = new ProductSpecVO();
        result.setProductBase(productBase);
        result.setSpecOptions(specOptions);
        result.setSpecPriceMap(specPriceMap);
        return result;
    }


    @Override
    @Transactional
    @CacheEvict(value = "product", allEntries = true) // 清除所有列表缓存（因库存变化可能影响列表）
    public boolean updateStock(Integer productId, Integer quantity) {
        // 参数校验
        if (productId == null || productId <= 0 || quantity == null || quantity <= 0) {
            throw new IllegalArgumentException("无效的产品ID或数量");
        }
        // 直接尝试更新，利用数据库条件
        return productMapper.decreaseStock(productId, quantity);
    }

    @Override
    public IPage<Product> getStock(IPage<Product> productIPage, String keyword, Integer userId , String category,Integer status) {
        return  productMapper.getStock(productIPage, keyword, userId,category, status);
    }

    @Override
    @Transactional

    public boolean toggleStatus(Integer productId) {
        Product product = baseMapper.selectById(productId);
        if (product == null) {
            return false; // 商品不存在
        }
        // 2. 切换状态（1→0，0→1）
        Integer currentStatus = product.getStatus();
        product.setStatus(currentStatus == 1 ? 0 : 1);

        // 3. 可以添加更新时间
        product.setUpdateTime(new java.util.Date());

        // 4. 更新到数据库
        return baseMapper.updateById(product) > 0;
    }


    // 查询库存是否预警
    @Override
    public IPage<Product> queryWarningProducts(Integer page, Integer size, String keyword,
                                               String category, String level,Integer merchantId) {
        // 1. 初始化分页对象
        Page<Product> productPage = new Page<>(page, size);

        // 2. 构建查询条件（MyBatis-Plus LambdaQueryWrapper）
        LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();

        // 2.1 筛选上架商品（状态为1）
        queryWrapper.eq(Product::getStatus, 1);

        //商家筛选
        queryWrapper.eq(Product::getMerchantId,merchantId);

        // 2.2 关键词搜索（匹配商品ID或商品名称）
        if (StringUtils.isNotBlank(keyword)) {
            queryWrapper.and(wrapper -> wrapper
                    .like(Product::getProductName, keyword)  // 商品名称模糊匹配
                    .or()
                    .eq(Product::getProductId, keyword));    // 商品ID精确匹配
        }

        // 2.3 分类筛选（精确匹配）
        if (StringUtils.isNotBlank(category)) {
            queryWrapper.eq(Product::getCategory, category);
        }

        // 2.4 预警级别筛选（核心逻辑：根据库存与阈值的比例判断）
        // 注意：这里假设商品表有warning_threshold字段（自定义阈值），若没有则使用默认阈值
        if (StringUtils.isNotBlank(level)) {
            // 计算阈值（优先使用商品自定义阈值，否则用默认值）
            // 由于Product实体未定义warning_threshold，这里用默认阈值演示
            Integer threshold = defaultThreshold;

            // 转换比例为小数（如30% → 0.3）
            double criticalRate = criticalRatio / 100.0;
            double warningRate = warningRatio / 100.0;

            switch (level) {
                case "critical":  // 严重不足：库存 ≤ 阈值*30% 或 库存为0
                    queryWrapper.and(wrapper -> wrapper
                            .le(Product::getStock, (int) (threshold * criticalRate))
                            .or()
                            .eq(Product::getStock, 0));
                    break;
                case "warning":   // 库存偏低：阈值*30% < 库存 ≤ 阈值*60%
                    queryWrapper.gt(Product::getStock, (int) (threshold * criticalRate))
                            .le(Product::getStock, (int) (threshold * warningRate));
                    break;
                case "normal":    // 接近预警：阈值*60% < 库存 ≤ 阈值
                    queryWrapper.gt(Product::getStock, (int) (threshold * warningRate))
                            .le(Product::getStock, threshold);
                    break;
            }
        } else {
            // 若未指定级别，默认查询所有库存 ≤ 阈值的商品（即所有需要预警的商品）
            queryWrapper.le(Product::getStock, defaultThreshold);
        }

        // 2.5 按库存升序排序（库存越少越优先显示）
        queryWrapper.orderByAsc(Product::getStock);

        // 3. 执行分页查询（MyBatis-Plus自动拼接SQL）
        return baseMapper.selectPage(productPage, queryWrapper);
    }
    /**
     * 新增商品及规格（优化后）
     */
    @Override
    @Transactional(rollbackFor = Exception.class) // 明确回滚所有异常
    @CacheEvict(value = "product", allEntries = true) // 清除所有列表缓存（因库存变化可能影响列表）
    public boolean saveAndSpec(ProductSubmitDTO productSubmitDTO, Integer merchantId) {
        // 1. 处理商品主信息
        Product product = convertToProduct(productSubmitDTO.getProduct(), merchantId, true);
        product.setStatus(2);
        productMapper.insert(product);

        // 2. 处理规格主数据（非空判断）
        ProductSpecDTO specDTO = productSubmitDTO.getProductSpec();
        if (specDTO != null && specDTO.getSpec() != null) {
            ProductSpec productSpec = convertToProductSpec(specDTO, product.getProductId(), product.getProductName());
            specMapper.insert(productSpec);
        }

        // 3. 处理规格价格（批量插入）
        List<ProductSpecPriceDTO> priceDTOs = productSubmitDTO.getProductSpecPrices();
        if (priceDTOs != null && !priceDTOs.isEmpty()) {
            List<ProductSpecPrice> specPrices = convertToSpecPrices(priceDTOs, product.getProductId());
            specPriceMapper.insert(specPrices); // 批量插入（MyBatis-Plus方法）
        }

        return true;
    }


    /**
     * 更新商品及规格（优化后）
     */
    @Override
    @Transactional(rollbackFor = Exception.class) // 明确回滚所有异常
    public boolean UpdateProduct(ProductSubmitDTO productSubmitDTO, Integer merchantId) {
        // 1. 处理商品主信息
        Product product = convertToProduct(productSubmitDTO.getProduct(), merchantId, false);
        productMapper.updateById(product);

        Integer productId = product.getProductId();

        // 2. 处理规格主数据（先删后增，保证数据一致性）
        ProductSpecDTO specDTO = productSubmitDTO.getProductSpec();
        // 删除旧规格
        specMapper.deleteByProductId(productId); // 需在SpecMapper中新增此方法
        // 插入新规格（非空判断）
        if (specDTO != null && specDTO.getSpec() != null) {
            ProductSpec productSpec = convertToProductSpec(specDTO, productId, product.getProductName());
            specMapper.insert(productSpec);
        }

        // 3. 处理规格价格（先删后增，避免旧数据残留）
        // 删除旧规格价格
        specPriceMapper.deleteByProductId(productId); // 需在SpecPriceMapper中新增此方法
        // 插入新规格价格（非空判断）
        List<ProductSpecPriceDTO> priceDTOs = productSubmitDTO.getProductSpecPrices();
        if (priceDTOs != null && !priceDTOs.isEmpty()) {
            List<ProductSpecPrice> specPrices = convertToSpecPrices(priceDTOs, productId);
            specPriceMapper.insert(specPrices); // 批量插入
        }

        return true;
    }

    @Override
    public IPage<Product> queryProductList(ProductReviewQueryDTO queryDTO) {
        Page<Product> page = new Page<>(queryDTO.getPage(), queryDTO.getSize());

        // 2. 构建多条件查询器（LambdaQueryWrapper防SQL注入）
        LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();

        // ① 关键词模糊查询：匹配商品名、商品ID、商家ID
        if (queryDTO.getKeyword() != null && !queryDTO.getKeyword().trim().isEmpty()) {
            String keyword = "%" + queryDTO.getKeyword().trim() + "%";
            queryWrapper.like(Product::getProductName, keyword) // 商品名模糊
                    .or()
                    .like(Product::getProductId, keyword) // 商品ID模糊
                    .or()
                    .like(Product::getMerchantId, keyword); // 商家ID模糊
        }

        // ② 审核状态筛选（0=拒绝，1=通过，2=待审核）3=审核失败
        if (queryDTO.getStatus() != null) {
            queryWrapper.eq(Product::getStatus, queryDTO.getStatus());
        }

        // ③ 分类筛选
        if (queryDTO.getCategory() != null && !queryDTO.getCategory().trim().isEmpty()) {
            queryWrapper.eq(Product::getCategory, queryDTO.getCategory().trim());
        }

        // ④ 日期范围筛选（按创建时间查询，可根据需求改为updateTime）
        if (queryDTO.getStartDate() != null) {
            queryWrapper.ge(Product::getCreateTime, queryDTO.getStartDate()); // ≥开始时间
        }
        if (queryDTO.getEndDate() != null) {
            queryWrapper.le(Product::getCreateTime, queryDTO.getEndDate()); // ≤结束时间
        }

        // 3. 执行分页查询（MyBatis-Plus自动分页）
        Page<Product> productPage = productMapper.selectPage(page, queryWrapper);

        return productPage;

    }

    @Override
    public ProductReviewStatsDTO getReviewStats() {
        ProductReviewStatsDTO stats = new ProductReviewStatsDTO();
        LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<>();

        // 1. 待审核商品数（status=2）
        wrapper.eq(Product::getStatus, 2);
        stats.setPendingCount(Math.toIntExact(count(wrapper))); // 直接调用父类的count()
        wrapper.clear();

        // 2. 已通过商品数（status=1）
        wrapper.eq(Product::getStatus, 1);
        stats.setApprovedCount(Math.toIntExact(count(wrapper)));
        wrapper.clear();

        // 3. 已拒绝商品数（status=0 或 3）
        wrapper.in(Product::getStatus, 0, 3);
        stats.setRejectedCount(Math.toIntExact(count(wrapper)));
        wrapper.clear();

        // 4. 今日新增审核数（createTime 在今日0点-24点之间）
        LocalDateTime todayStart = LocalDateTime.now().with(LocalTime.MIN);
        LocalDateTime todayEnd = LocalDateTime.now().with(LocalTime.MAX);
        wrapper.ge(Product::getCreateTime, todayStart)
                .le(Product::getCreateTime, todayEnd);
        stats.setTodayNewCount(Math.toIntExact(count(wrapper)));

        return stats;
    }

    /**
     * 处理商品审核（通过/拒绝）
     */
    @Override
    @Transactional
    @CacheEvict(value = "product", allEntries = true) // 清除所有列表缓存（因库存变化可能影响列表）
    public void handleReview(Integer productId, ReviewSubmitDTO reviewDTO) {
        // 1. 校验商品是否存在
        Product product = productMapper.selectById(productId);
        if (product == null) {
            throw new BusinessException("商品不存在，无法审核");
        }

        // 2. 校验商品当前状态是否为“待审核”（只有待审核状态才能操作）
        if (product.getStatus() != 2) {
            throw new BusinessException("只有待审核的商品才能执行此操作");
        }

        // 3. 校验审核状态是否合法（只能是1=通过或3=拒绝）
        Integer status = reviewDTO.getStatus();
        if (status != 1 && status != 3) {
            throw new BusinessException("审核状态不合法");
        }

        // 4. 更新商品信息（状态、审核意见、更新时间）
        product.setStatus(status); // 更新审核状态
        product.setReason(reviewDTO.getComment()); // 保存审核意见
        product.setUpdateTime(new Date()); // 更新时间戳

        // 5. 保存到数据库
        int rows = productMapper.updateById(product);
        if (rows <= 0) {
            throw new BusinessException("审核状态更新失败，请重试");
        }
    }

    @Override
    @Transactional
    public void resetToPending(Integer productId) {
            // 1. 校验商品是否存在
            Product product = productMapper.selectById(productId);
            if (product == null) {
                throw new BusinessException("商品不存在，无法重置审核状态");
            }

            // 2. 校验是否需要重置（如果已是待审核状态，无需操作）
            if (product.getStatus() == 2) {
                throw new BusinessException("商品当前已是待审核状态，无需重复操作");
            }

            // 3. 更新状态为“待审核”，并刷新更新时间
            product.setStatus(2); // 2=待审核
            product.setUpdateTime(new Date()); // 更新时间戳
            // 可选：清除历史审核意见（根据业务需求决定是否保留）
            // product.setReviewComment(null);

            // 4. 保存到数据库
            int rows = productMapper.updateById(product);
            if (rows <= 0) {
                throw new BusinessException("重置审核状态失败，请重试");
            }

    }

    // ------------------------- 以下为抽取的工具方法（减少重复代码） -------------------------

    /**
     * 转换ProductDTO为Product实体
     * @param productDTO 前端传递的商品DTO
     * @param merchantId 商户ID
     * @param isNew 是否为新增（新增需设置创建时间）
     */
    private Product convertToProduct(Product productDTO, Integer merchantId, boolean isNew) {
        Product product = new Product();
        BeanUtils.copyProperties(productDTO, product); // 简化属性复制
        product.setMerchantId(merchantId);
        product.setUpdateTime(new Date());
        if (isNew) {
            product.setCreateTime(new Date()); // 新增时才设置创建时间
        }
        return product;
    }

    /**
     * 转换ProductSpecDTO为ProductSpec实体（含JSON序列化）
     */
    private ProductSpec convertToProductSpec(ProductSpecDTO specDTO, Integer productId, String productName) {
        ProductSpec productSpec = new ProductSpec();
        productSpec.setProductId(productId);
        productSpec.setProductName(productName);
        try {
            // 抽取JSON序列化逻辑，统一处理
            String specJson = objectMapper.writeValueAsString(specDTO.getSpec());
            productSpec.setSpec(specJson);
        } catch (JsonProcessingException e) {
            // 异常信息添加上下文，便于调试
            throw new BusinessException("商品规格序列化失败：productId=" + productId);
        }
        return productSpec;
    }

    /**
     * 批量转换ProductSpecPriceDTO为ProductSpecPrice实体（含JSON序列化）
     */
    private List<ProductSpecPrice> convertToSpecPrices(List<ProductSpecPriceDTO> priceDTOs, Integer productId) {
        return priceDTOs.stream().map(dto -> {
            ProductSpecPrice specPrice = new ProductSpecPrice();
            specPrice.setProductId(productId);
            specPrice.setPrice(dto.getPrice());
            try {
                String comboJson = objectMapper.writeValueAsString(dto.getSpecCombo());
                specPrice.setSpecCombo(comboJson);
            } catch (JsonProcessingException e) {
                throw new BusinessException("规格组合序列化失败：productId=" + productId);
            }
            return specPrice;
        }).collect(Collectors.toList());
    }

}
